/*
 * Copyright (c) 2009, Katholieke Universiteit Leuven
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the Katholieke Universiteit Leuven nor the names of
 *       its contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * @addtogroup lib
 * @{
 * @defgroup vector Vector library
 * @{
 */
/**
 * @file
 * Header file for the Vector library
 * @author 
 * Wouter Horré <wouter.horre@cs.kuleuven.be>
 */
#ifndef __LOOCI_LIB_VECTOR_H__
#define __LOOCI_LIB_VECTOR_H__

#include "contiki.h"
#include "mmem.h"
#include "sys/cc.h"

/**
 * The blocksize of the vector data structure.
 */
#define VECTOR_BLOCKSIZE 5

/**
 * @name Return values
 * @{
 */
/**
 * Operation completed successful.
 *
 * @hideinitializer
 */
#define VECTOR_OK 1
/**
 * Failure during the execution of the operation.
 *
 * @hideinitializer
 */
#define VECTOR_FAIL 0
/** @} */

/**
 * The data structure for a vector.
 */
struct vector {
  u8_t len;
  u8_t elementsize;
  struct vector_block * first;
};

/**
 * The data structure for a vector block.
 */
struct vector_block {
  struct mmem * next;
  struct mmem mmem_next;
  char elements[];
};

/**
 * @name Application Programming Interface (API)
 * @{
 */
/**
 * Initialize the vector library
 *
 * Must be called before any of the other the methods in the API.
 */
void vector_libinit();

/**
 * Declare a vector.
 *
 * Afterwards 'name' can be used as a vector (i.e. it is of
 * type struct vector).
 *
 * @hideinitializer
 */
#define VECTOR(name, structure) static char CC_CONCAT(vector_block_,name) \
  [sizeof(struct vector_block)+sizeof(structure)*VECTOR_BLOCKSIZE]; \
  static struct vector name = { 0, sizeof(structure), (struct vector_block*) CC_CONCAT(vector_block_,name) } 

/**
 * Initialize a vector declared with VECTOR()
 *
 * @param vector A pointer to a vector that was previously 
 *               declared with VECTOR()
 */
void vector_init(struct vector * vector);

/**
 * Initialize a vector declared with VECTOR()
 *
 * @param vector A pointer to a vector that was previously 
 *               declared with VECTOR()
 */
u8_t vector_len(struct vector * vector);

/**
 * Add an element to a vector.
 *
 * @param vector A pointer to a vector that was previously 
 *               declared with VECTOR()
 * @param element The element to add.
 *
 * @return VECTOR_OK The element was successfully added
 * @return VECTOR_FAIL The element could not be added
 */
u8_t vector_add(struct vector * vector, void * element);

/**
 * Get an element from a vector.
 *
 * @param vector A pointer to a vector that was previously 
 *               declared with VECTOR()
 * @param index The index of the element to retrieve. Index starts at zero!
 *
 * @return A pointer to the element at the given index.
 * @return NULL If the index is larger than the length of the vector.
 *
 * @note The returned pointer may become invalid over time (i.e.
 *       it is not guaranteed to stay valid after a protothread/contiki 
 *       process wait).
 */
void * vector_get(struct vector * vector, u8_t index);

/**
 * Remove an element from a vector.
 *
 * @param vector A pointer to a vector that was previously
 *               declared with VECTOR()
 * @param index The index of the element to remove. Index starts at zero!
 *
 * @note After this operation all pointers to elements of the vector are invalid!!!
 */
void vector_remove(struct vector * vector, u8_t index);

/** @} */

#endif

/** @} */
/** @} */
